home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / calc / calc.c next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  24.0 KB  |  777 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18.  
  19. /******************************************************************************
  20.  *                                                                            *
  21.  *                Reverse-Polish-Notation (RPN) calculator                    *
  22.  *                                                                            *
  23.  *                Written by Tom Davis 1991                                   *
  24.  *                                                                            *
  25.  *                                                                            *
  26.  * Calc is a Reverse-Polish-Notation (RPN) calculator.  You must enter the    *
  27.  * operands first, then the operation.  For example, to add 3 and 4, press    *
  28.  * [3] [Enter] [4] [+].  If the operation is unary, like sine, it operates    *
  29.  * on the bottom element of the display. To take the sine of .54, do:         *
  30.  *                                                                            *
  31.  * [.] [5] [4] [Sin].                                                         *
  32.  *                                                                            *
  33.  * The last 6 entries of the stack are visible, and you can scroll to see the *
  34.  * rest.  All operations are performed on the element(s) at the bottom of the *
  35.  * stack.  The bottom element is called 'x' and the next element up is called *
  36.  * 'y'.                                                                       *
  37.  *                                                                            *
  38.  * The [+/-] key changes the sign of x.  To find the cosine of -.22, do:      *
  39.  *                                                                            *
  40.  * [.] [2] [2] [+/-] [Cos].                                                   *
  41.  *                                                                            *
  42.  * The [Inv] key changes the operation of some of the other keys so they      *
  43.  * perform the inverse operation.  It is only active for one keystroke.       *
  44.  * Press [Inv] again to cancel the operation.                                 *
  45.  *                                                                            *
  46.  * [Sto] and [Rcl] stores and recalls a single value.                         *
  47.  *                                                                            *
  48.  * [Dup2] duplicates the bottom 2 items on the stack.                         *
  49.  *                                                                            *
  50.  * [Roll] rolls all the stack elements down one, and puts the bottom element  *
  51.  * on the top.                                                                *
  52.  *                                                                            *
  53.  * [Exch] swaps the bottom two elements.                                      *
  54.  *                                                                            *
  55.  * [Int] gives the integer part.                                              *
  56.  *                                                                            *
  57.  * [Inv] [Frac] gives the fractional part.                                    *
  58.  *                                                                            *
  59.  * [Clr] clears the bottom element to zero.  Use this when you get some kind  *
  60.  * of error.                                                                  *
  61.  *                                                                            *
  62.  * [B10] and [B16] put you in base 10 or base 16 mode.  Numbers with          *
  63.  * fractional parts are always displayed in base 10.  In base 16 mode, the    *
  64.  * keys [a] through [f] are used for numeric entry.  They do nothing,         *
  65.  * otherwise.                                                                 *
  66.  *                                                                            *
  67.  * [And], [Or] and [Not] are logical operations on 32 bit integers.  If       *
  68.  * there's a fractional part, they don't do anything.                         *
  69.  *                                                                            *
  70.  * To remember a sequence of keystrokes, press [Prog], then the sequence of   *
  71.  * keystrokes, and then [Prog] again.  For example, if you want to            *
  72.  * calculate x^2 + y^2 repeatedly, where x and y are the two bottom entries   *
  73.  * of the stack, do this:                                                     *
  74.  *                                                                            *
  75.  * [Prog] [Inv] [x^2] [Exch] [Inv] [x^2] [+] [Prog].                          *
  76.  *                                                                            *
  77.  * Then, to calculate 5^2+7^2, do this:                                       *
  78.  *                                                                            *
  79.  * [5] [Enter] [7] [Run].                                                     *
  80.  *                                                                            *
  81.  * The following keys from the computer keyboard are understood by calc:      *
  82.  *                                                                            *
  83.  * [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [.], [Enter],            *
  84.  * [+], [-], [*], [/], [a], [b], [c], [d], [e], [f].                          *
  85.  *                                                                            *
  86.  ******************************************************************************/
  87.  
  88. #include <gl.h>
  89. #include <device.h>
  90. #include <math.h>
  91. #include <stdlib.h>
  92. #include "showcaseui.h"
  93. #include "calc.h"
  94.  
  95. #define Bwidth            44
  96. #define Bheight         25
  97. #define Bhspace         10
  98. #define Bvspace            10
  99. #define Displaylines    6
  100.  
  101. #define Stackdepth  200
  102. #define PI      3.14159265358979323
  103.  
  104. char *CS[Stackdepth+Displaylines];
  105.  
  106. double calcdata[Stackdepth+Displaylines];
  107.  
  108. long CSP = Displaylines-1;
  109. long invmode = 0;
  110. long base = 10;
  111. float memory = 0.0;
  112. long degreemode = 1;
  113.  
  114. long savingprog = 0;
  115. long program[5000];
  116. long proglen = 0;
  117.  
  118. #define WIDTH 6
  119. #define HEIGHT 8
  120.  
  121. struct calcbutton {
  122.     char *label, *invlabel;
  123.     Button *b;
  124.     long type;
  125. } keypad[HEIGHT][WIDTH];
  126.  
  127. TextList *cdisplay;
  128.  
  129. void loadcb(long row, long col, char *lab, char *invlab, long type)
  130. {
  131.     struct calcbutton *cb = &keypad[row][col];
  132.     cb->label = lab;
  133.     cb->invlabel = invlab;
  134.     cb->type = type;
  135.     cb->b = newbut(Bhspace+col*(Bhspace+Bwidth), Bvspace+row*(Bvspace+Bheight),
  136.            (col+1)*(Bhspace+Bwidth), (row+1)*(Bvspace+Bheight));
  137.     loadbut(cb->b, lab);
  138. }
  139.  
  140. void initkeypad()
  141. {
  142.     loadcb(0, 0, "Exch", "Exch", Exchkey);
  143.     loadcb(0, 1, "0", "0", Zerokey);
  144.     loadcb(0, 2, ".", ".", Dotkey);
  145.     loadcb(0, 3, "+/-", "+/-", Flipsignkey);
  146.     loadcb(0, 4, "/", "/", Dividekey);
  147.     loadcb(0, 5, "Deg", "Deg", Radkey);
  148.     loadcb(1, 0, "Roll", "Roll", Rollkey);
  149.     loadcb(1, 1, "1", "1", Onekey);
  150.     loadcb(1, 2, "2", "2", Twokey);
  151.     loadcb(1, 3, "3", "3", Threekey);
  152.     loadcb(1, 4, "*", "*", Timeskey);
  153.     loadcb(1, 5, "Clr", "Clr", Clearkey);
  154.     loadcb(2, 0, "Dup2", "Dup2", Dup2key);
  155.     loadcb(2, 1, "4", "4", Fourkey);
  156.     loadcb(2, 2, "5", "5", Fivekey);
  157.     loadcb(2, 3, "6", "6", Sixkey);
  158.     loadcb(2, 4, "-", "-", Minuskey);
  159.     loadcb(2, 5, "And", "And", Andkey);
  160.     loadcb(3, 0, "Enter", "Enter", Enterkey);
  161.     loadcb(3, 1, "7", "7", Sevenkey);
  162.     loadcb(3, 2, "8", "8", Eightkey);
  163.     loadcb(3, 3, "9", "9", Ninekey);
  164.     loadcb(3, 4, "+", "+", Pluskey);
  165.     loadcb(3, 5, "Or", "Or", Orkey);
  166.     loadcb(4, 0, "Sin", "Asin", Sinkey);
  167.     loadcb(4, 1, "Cos", "Acos", Coskey);
  168.     loadcb(4, 2, "Tan", "Atan", Tankey);
  169.     loadcb(4, 3, "Int", "Frac", Intkey);
  170.     loadcb(4, 4, "Help", "Help", Helpkey);
  171.     loadcb(4, 5, "Not", "Not", Notkey);
  172.     loadcb(5, 0, "e^x", "Ln", Expkey);
  173.     loadcb(5, 1, "10^x", "Log", Tentoxkey);
  174.     loadcb(5, 2, "Sqrt", "x^2", Sqrtkey);
  175.     loadcb(5, 3, "y^x", "y^(1/x)", Xtoykey);
  176.     loadcb(5, 4, "Run", "Run", Runkey);
  177.     loadcb(5, 5, "B16", "B16", Base16key);
  178.     loadcb(6, 0, "Inv", "Inv", Invkey);
  179.     loadcb(6, 1, "Rcl", "Rcl", Recallkey);
  180.     loadcb(6, 2, "Sto", "Sto", Storekey);
  181.     loadcb(6, 3, "1/x", "1/x", Oneoverkey);
  182.     loadcb(6, 4, "Prog", "Prog", Progkey);
  183.     loadcb(6, 5, "B10", "B10", Base10key);
  184.     loadcb(7, 0, "a", "a", Akey);
  185.     loadcb(7, 1, "b", "b", Bkey);
  186.     loadcb(7, 2, "c", "c", Ckey);
  187.     loadcb(7, 3, "d", "d", Dkey);
  188.     loadcb(7, 4, "e", "e", Ekey);
  189.     loadcb(7, 5, "f", "f", Fkey);
  190.     cdisplay = newtl(Bhspace, HEIGHT*Bheight + (HEIGHT+1)*Bvspace,
  191.              WIDTH*(Bhspace+Bwidth), Displaylines);
  192.     settlstrslinkhandle(CS, cdisplay);
  193. }
  194.  
  195. void drawdisplay()
  196. {
  197.     settltop(cdisplay, CSP - Displaylines + 1);
  198.     cdisplay->count = CSP+1;
  199.     adjustslider(cdisplay, cdisplay->vs);
  200.     setvsarrowdelta(cdisplay->vs, 1);
  201.     drawtl(cdisplay); swapbuffers();
  202. }
  203.  
  204. void drawkeypad()
  205. {
  206.     long i, j;
  207.  
  208.     backgroundclear();
  209.     for (i = 0; i < HEIGHT; i++)
  210.         for (j = 0; j < WIDTH; j++)
  211.         drawbut(keypad[i][j].b);
  212.     drawdisplay();
  213. }
  214.  
  215. loadbuttons(long inv)
  216. {
  217.     long i, j;
  218.  
  219.     for (i = 0; i < HEIGHT; i++)
  220.         for (j = 0; j < WIDTH; j++) {
  221.         if (inv)
  222.             loadbut(keypad[i][j].b, keypad[i][j].invlabel);
  223.         else
  224.             loadbut(keypad[i][j].b, keypad[i][j].label);
  225.     }
  226.     drawkeypad();
  227.     drawkeypad();
  228. }
  229.  
  230. void locatekeypad(long x, long y)
  231. {
  232.     long i, j;
  233.  
  234.     for (i = 0; i < HEIGHT; i++)
  235.         for (j = 0; j < WIDTH; j++) {
  236.         locatebut(keypad[i][j].b, x, y);
  237.     }
  238.     locatevs(cdisplay->vs, x, y);
  239. }
  240.  
  241. long getclick(long x, long y)
  242. {
  243.     long i, j, k;
  244.  
  245.     for (i = 0; i < HEIGHT; i++)
  246.         for (j = 0; j < WIDTH; j++) {
  247.         if (inbut(keypad[i][j].b, x, y)) {
  248.         k = pressbut(keypad[i][j].b, x, y);
  249.         if (k) return keypad[i][j].type;
  250.         return 0;
  251.         }
  252.     }
  253.     return 0;
  254. }
  255.  
  256. long xorg, yorg;
  257.  
  258. void initcalc()
  259. {
  260.     long i;
  261.     
  262. /*foreground();*/
  263.     prefsize(WIDTH*Bwidth+(WIDTH+1)*Bhspace,
  264.         HEIGHT*Bheight+(HEIGHT+2)*Bvspace+Displaylines*TEXTHEIGHT+7);
  265.     winopen("RPN Calc");
  266.     icontitle("RPN Calc");
  267.     wintitle("RPN Calc");
  268.     doublebuffer();
  269.     gconfig();
  270.     getorigin(&xorg, &yorg);
  271.     initui();
  272.     initbut();
  273.     inittl();
  274.     for (i = 0; i < Stackdepth+Displaylines; i++) {
  275.         CS[i] = (char *)malloc(50);
  276.     *CS[i] = ' ';
  277.     *(CS[i]+1) = 0;
  278.     }
  279.     initkeypad();
  280.     qdevice(MOUSEX); qdevice(MOUSEY);
  281.     glcompat(GLC_MQUEUERATE, GLC_COMPATRATE);
  282.     qdevice(LEFTMOUSE);
  283.     qdevice(KEYBD);
  284.     qdevice(PAD0); qdevice(PAD1); qdevice(PAD2); qdevice(PAD3); qdevice(PAD4);
  285.     qdevice(PAD5); qdevice(PAD6); qdevice(PAD7); qdevice(PAD8); qdevice(PAD9);
  286.     qdevice(PADPERIOD);
  287. }
  288.  
  289. void interpclick(long);
  290. void interpkeybd(long);
  291. void showhelp();
  292.  
  293. formatentry(long s)
  294. {
  295.     if (calcdata[s] - trunc(calcdata[s]) == 0 &&
  296.             (calcdata[s] < 1.0e9 && -1.0e9 < calcdata[s])) {
  297.     if (base == 10) {
  298.         sprintf(CS[s], "%15d", (long)calcdata[s]);
  299.     } else {
  300.         sprintf(CS[s], "0x%13x", (long)calcdata[s]);
  301.     }
  302.     } else {
  303.         if (calcdata[s] < 1.0e9 && -1.0e9 < calcdata[s] &&
  304.         (calcdata[s] > 1.0e-5 || calcdata[s] < -1.0e-5))
  305.             sprintf(CS[s], "%15.12f", calcdata[s]);
  306.     else
  307.         sprintf(CS[s], "%15.12e", calcdata[s]);
  308.     }
  309. }
  310.  
  311. main()
  312. {
  313.     short   dev, val;
  314.     long    xval, yval;
  315.  
  316.     initcalc();
  317.     xval = getvaluator(MOUSEX);
  318.     yval = getvaluator(MOUSEY);
  319.     drawkeypad(); drawkeypad();
  320.     formatentry(Displaylines-1);
  321.     drawdisplay();
  322.     while(1) {
  323.     dev = qread(&val);
  324.     switch(dev) {
  325.         case MOUSEX:
  326.             xval = val;
  327.         locatekeypad(xval-xorg, yval-yorg);
  328.         break;
  329.         case MOUSEY:
  330.             yval = val;
  331.         locatekeypad(xval-xorg, yval-yorg);
  332.         break;
  333.         case LEFTMOUSE:
  334.             if (val == 0) break;
  335.         if (invs(cdisplay->vs, xval-xorg, yval-yorg)) {
  336.             selectedvs(cdisplay->vs, cdisplay, xval-xorg, yval-yorg, 1);
  337.         } else
  338.             interpclick(getclick(xval-xorg, yval-yorg));
  339.         break;
  340.         case KEYBD:
  341.             interpkeybd(val);
  342.         break;
  343.         case PAD0: if (val == 1) interpkeybd('0'); break;
  344.         case PAD1: if (val == 1) interpkeybd('1'); break;
  345.         case PAD2: if (val == 1) interpkeybd('2'); break;
  346.         case PAD3: if (val == 1) interpkeybd('3'); break;
  347.         case PAD4: if (val == 1) interpkeybd('4'); break;
  348.         case PAD5: if (val == 1) interpkeybd('5'); break;
  349.         case PAD6: if (val == 1) interpkeybd('6'); break;
  350.         case PAD7: if (val == 1) interpkeybd('7'); break;
  351.         case PAD8: if (val == 1) interpkeybd('8'); break;
  352.         case PAD9: if (val == 1) interpkeybd('9'); break;
  353.         case PADPERIOD: if (val == 1) interpkeybd('.'); break;
  354.         case REDRAW:
  355.             getorigin(&xorg, &yorg);
  356.             drawkeypad(); drawkeypad();
  357.     }
  358.     }
  359. }
  360.  
  361. long inputptr = 0;
  362. long enablepush = 0;
  363.  
  364. void push()
  365. {
  366.     CSP++;
  367.     inputptr = 0;
  368.     *CS[CSP] = ' ';
  369.     *(CS[CSP]+1) = 0;
  370. }
  371.  
  372. void doenter()
  373. {
  374.     long isdot = 0;
  375.     
  376.     char *s = CS[CSP];
  377.     while (*s) {if (*s++ == '.') isdot=1; }
  378.     if (enablepush) {
  379.     strcpy(CS[CSP+1], CS[CSP]);
  380.     calcdata[CSP+1] = calcdata[CSP];
  381.     CSP++;
  382.     } else {
  383.         if (isdot || base == 10)
  384.         calcdata[CSP] = atof(CS[CSP]);
  385.     else
  386.         calcdata[CSP] = strtol(CS[CSP], 0, 16);
  387.     enablepush = 1;
  388.     inputptr = 0;
  389.     }
  390.     formatentry(CSP);
  391.     drawdisplay();
  392. }
  393.  
  394. void binop(char c)
  395. {
  396.     long i, j;
  397.  
  398.     if (enablepush == 0) doenter();
  399.     if (CSP < Displaylines) return;
  400.     switch (c) {
  401.     case '+':
  402.         calcdata[CSP-1] = calcdata[CSP-1] + calcdata[CSP];
  403.         break;
  404.     case '-':
  405.         calcdata[CSP-1] = calcdata[CSP-1] - calcdata[CSP];
  406.         break;
  407.     case '*':
  408.         calcdata[CSP-1] = calcdata[CSP-1] * calcdata[CSP];
  409.         break;
  410.     case '/':
  411.         calcdata[CSP-1] = calcdata[CSP-1] / calcdata[CSP];
  412.         break;
  413.     case '^':
  414.         if (invmode == 0)
  415.             calcdata[CSP-1] = pow(calcdata[CSP-1], calcdata[CSP]);
  416.         else
  417.             calcdata[CSP-1] = pow(calcdata[CSP-1], 1.0/calcdata[CSP]);
  418.         break;
  419.     case '&':
  420.         if (calcdata[CSP-1] - trunc(calcdata[CSP-1]) != 0) return;
  421.         if (calcdata[CSP] - trunc(calcdata[CSP]) != 0) return;
  422.         i = calcdata[CSP-1]; j = calcdata[CSP];
  423.         calcdata[CSP-1] = (long)(i&j);
  424.         break;
  425.     case '|':
  426.         if (calcdata[CSP-1] - trunc(calcdata[CSP-1]) != 0) return;
  427.         if (calcdata[CSP] - trunc(calcdata[CSP]) != 0) return;
  428.         i = calcdata[CSP-1]; j = calcdata[CSP];
  429.         calcdata[CSP-1] = (long)(i|j);
  430.         break;
  431.     }
  432.     CS[CSP][0] = 0;
  433.     CSP--;
  434.     formatentry(CSP);
  435.     drawdisplay();
  436.     enablepush = 1;
  437. }
  438.  
  439. void unop(long c)
  440. {
  441.     long i;
  442.  
  443.     if (enablepush == 0) doenter();
  444.     switch (c) {
  445.         case Storekey:
  446.         memory = calcdata[CSP];
  447.         break;
  448.     case Recallkey:
  449.         doenter();
  450.         calcdata[CSP] = memory;
  451.         break;
  452.     case Flipsignkey:
  453.         calcdata[CSP] = -calcdata[CSP];
  454.         break;
  455.     case Oneoverkey:
  456.         calcdata[CSP] = 1.0/calcdata[CSP];
  457.         break;
  458.     case Clearkey:
  459.         calcdata[CSP] = 0.0;
  460.         enablepush = 0;
  461.         formatentry(CSP);
  462.         drawdisplay();
  463.         return;
  464.     case Sinkey:
  465.         if (invmode) {
  466.             calcdata[CSP] = asin(calcdata[CSP]);
  467.         if (degreemode) calcdata[CSP] *= 180.0/PI;
  468.         } else {
  469.         if (degreemode) calcdata[CSP] *= PI/180.0;
  470.             calcdata[CSP] = sin(calcdata[CSP]);
  471.         }
  472.         break;
  473.     case Coskey:
  474.         if (invmode) {
  475.             calcdata[CSP] = acos(calcdata[CSP]);
  476.         if (degreemode) calcdata[CSP] *= 180.0/PI;
  477.         } else {
  478.         if (degreemode) calcdata[CSP] *= PI/180.0;
  479.             calcdata[CSP] = cos(calcdata[CSP]);
  480.         }
  481.         break;
  482.     case Tankey:
  483.         if (invmode) {
  484.             calcdata[CSP] = atan(calcdata[CSP]);
  485.         if (degreemode) calcdata[CSP] *= 180.0/PI;
  486.         } else {
  487.         if (degreemode) calcdata[CSP] *= PI/180.0;
  488.             calcdata[CSP] = tan(calcdata[CSP]);
  489.         }
  490.         break;
  491.     case Tentoxkey:
  492.         if (invmode)
  493.             calcdata[CSP] = log10(calcdata[CSP]);
  494.         else
  495.             calcdata[CSP] = pow(10, calcdata[CSP]);
  496.         break;
  497.     case Expkey:
  498.         if (invmode)
  499.             calcdata[CSP] = log(calcdata[CSP]);
  500.         else
  501.             calcdata[CSP] = exp(calcdata[CSP]);
  502.         break;
  503.     case Intkey:
  504.         if (invmode)
  505.             calcdata[CSP] = calcdata[CSP] - trunc(calcdata[CSP]);
  506.         else
  507.             calcdata[CSP] = trunc(calcdata[CSP]);
  508.         break;
  509.     case Sqrtkey:
  510.         if (invmode==0)
  511.             calcdata[CSP] = sqrt(calcdata[CSP]);
  512.         else
  513.             calcdata[CSP] = calcdata[CSP]*calcdata[CSP];
  514.         break;
  515.     case Notkey:
  516.         if (calcdata[CSP] - trunc(calcdata[CSP]) != 0) return;
  517.         i = calcdata[CSP];
  518.         calcdata[CSP] = (long)(~i);
  519.         break;
  520.     }
  521.     formatentry(CSP);
  522.     drawdisplay();
  523.     enablepush = 1;
  524. }
  525.  
  526. void interpclick(long x)
  527. {
  528.     long i, rcount;
  529.     float f;
  530.     char *c;
  531.     
  532.     if (x == 0) return;
  533.     if (savingprog && x != Progkey && x != Runkey)
  534.         program[proglen++] = x;
  535.     if ((Zerokey <= x && x <= Ninekey) || x == Dotkey ||
  536.         (base == 16) && (Akey <= x && x <= Fkey)) {
  537.         if (enablepush) push();
  538.     enablepush = 0;
  539.     if (x == Dotkey)
  540.         CS[CSP][inputptr++] = '.';
  541.     else if (Akey <= x && x <= Fkey)
  542.         CS[CSP][inputptr++] = 'a' + x - Akey;
  543.     else
  544.         CS[CSP][inputptr++] = '0'+x-Zerokey;
  545.     CS[CSP][inputptr] = 0;
  546.     drawdisplay();
  547.     } else switch (x) {
  548.     case Pluskey:
  549.         binop('+'); break;
  550.     case Minuskey:
  551.         binop('-'); break;
  552.     case Timeskey:
  553.         binop('*'); break;
  554.     case Dividekey:
  555.         binop('/'); break;
  556.     case Xtoykey:
  557.         binop('^'); break;
  558.     case Helpkey:
  559.         showhelp(); break;
  560.     case Clearkey:
  561.         unop(Clearkey); break;
  562.     case Flipsignkey:
  563.         unop(Flipsignkey); break;
  564.     case Enterkey:
  565.         doenter();
  566.         break;
  567.     case Exchkey:
  568.         if (CSP < Displaylines) break;
  569.         if (enablepush == 0) doenter();
  570.         f = calcdata[CSP];
  571.         calcdata[CSP] = calcdata[CSP-1];
  572.         calcdata[CSP-1] = f;
  573.         c = CS[CSP];
  574.         CS[CSP] = CS[CSP-1];
  575.         CS[CSP-1] = c;
  576.         drawdisplay();
  577.         break;
  578.     case Rollkey:
  579.         if (CSP < Displaylines) break;
  580.         rcount = CSP - Displaylines+1;
  581.         if (enablepush == 0) doenter();
  582.         f = calcdata[CSP];
  583.         c = CS[CSP];
  584.         for (i = 0; i < rcount; i++) {
  585.         calcdata[CSP-i] = calcdata[CSP-i-1];
  586.         CS[CSP-i] = CS[CSP-i-1];
  587.         }
  588.         calcdata[CSP-rcount] = f;
  589.         CS[CSP-rcount] = c;
  590.         drawdisplay();
  591.         break;
  592.     case Dup2key:
  593.         if (CSP < Displaylines) break;
  594.         if (enablepush == 0) doenter();
  595.         strcpy(CS[CSP+2], CS[CSP]);
  596.         calcdata[CSP+2] = calcdata[CSP];
  597.         strcpy(CS[CSP+1], CS[CSP-1]);
  598.         calcdata[CSP+1] = calcdata[CSP-1];
  599.         CSP += 2;
  600.         drawdisplay();
  601.         break;
  602.     case Radkey:
  603.         if (degreemode) {
  604.                 loadcb(0, 5, "Rad", "Rad", Radkey);
  605.         } else {
  606.                 loadcb(0, 5, "Deg", "Deg", Radkey);
  607.         }
  608.         degreemode = 1 - degreemode;
  609.         loadbuttons(invmode);
  610.         break;
  611.     case Invkey:
  612.         if (invmode) {
  613.         invmode = 0;
  614.         loadbuttons(0);
  615.         } else {
  616.         invmode = 2;
  617.         loadbuttons(1);
  618.         }
  619.         break;
  620.     case Progkey:
  621.         if (savingprog == 0) {
  622.         proglen = 0;
  623.         }
  624.         savingprog = 1 - savingprog;
  625.         break;
  626.     case Runkey:
  627.         if (savingprog) break;
  628.         for (i = 0; i < proglen; i++)
  629.             interpclick(program[i]);
  630.         break;
  631.     case Storekey:
  632.         unop(Storekey); break;
  633.     case Recallkey:
  634.         unop(Recallkey); break;
  635.     case Oneoverkey:
  636.         unop(Oneoverkey); break;
  637.     case Sinkey:
  638.         unop(Sinkey); break;
  639.     case Coskey:
  640.         unop(Coskey); break;
  641.     case Tankey:
  642.         unop(Tankey); break;
  643.     case Expkey:
  644.         unop(Expkey); break;
  645.     case Tentoxkey:
  646.         unop(Tentoxkey); break;
  647.     case Intkey:
  648.         unop(Intkey); break;
  649.     case Andkey:
  650.         binop('&'); break;
  651.     case Orkey:
  652.         binop('|'); break;
  653.     case Notkey:
  654.         unop(Notkey); break;
  655.     case Base10key:
  656.         if (enablepush == 0) doenter();
  657.         base = 10;
  658.         for (i = Displaylines-1; i <= CSP; i++)
  659.             formatentry(i);
  660.         drawdisplay();
  661.         break;
  662.     case Base16key:
  663.         if (enablepush == 0) doenter();
  664.         base = 16;
  665.         for (i = Displaylines-1; i <= CSP; i++)
  666.             formatentry(i);
  667.         drawdisplay();
  668.         break;
  669.     case Sqrtkey:
  670.         unop(Sqrtkey); break;
  671.     }
  672.     if (invmode == 1) {
  673.     loadbuttons(0);
  674.     }
  675.     if (invmode > 0) invmode--;
  676. }
  677.  
  678. void interpkeybd(long x)
  679. {
  680.     switch (x) {
  681.     case 'A': case 'a': interpclick(Akey); break;
  682.     case 'B': case 'b': interpclick(Bkey); break;
  683.     case 'C': case 'c': interpclick(Ckey); break;
  684.     case 'D': case 'd': interpclick(Dkey); break;
  685.     case 'E': case 'e': interpclick(Ekey); break;
  686.     case 'F': case 'f': interpclick(Fkey); break;
  687.     case '0': interpclick(Zerokey); break;
  688.     case '1': interpclick(Onekey); break;
  689.     case '2': interpclick(Twokey); break;
  690.     case '3': interpclick(Threekey); break;
  691.     case '4': interpclick(Fourkey); break;
  692.     case '5': interpclick(Fivekey); break;
  693.     case '6': interpclick(Sixkey); break;
  694.     case '7': interpclick(Sevenkey); break;
  695.     case '8': interpclick(Eightkey); break;
  696.     case '9': interpclick(Ninekey); break;
  697.     case '.': interpclick(Dotkey); break;
  698.     case '+': interpclick(Pluskey); break;
  699.     case '-': interpclick(Minuskey); break;
  700.     case '*': interpclick(Timeskey); break;
  701.     case '/': interpclick(Dividekey); break;
  702.     case '\n': case '\r': interpclick(Enterkey); break;
  703.     }
  704. }
  705.  
  706. void showhelp()
  707. {
  708. printf("\n\n------------------------------------------\n\n");
  709. printf("Calc is a Reverse-Polish-Notation (RPN) calculator.  You\n");
  710. printf("must enter the operands first, then the operation.  For\n");
  711. printf("example, to add 3 and 4, press [3] [Enter] [4] [+].  If\n");
  712. printf("the operation is unary, like sine, it operates on the bottom\n");
  713. printf("element of the display.  To take the sine of .54, do:\n");
  714. printf("\n");
  715. printf("[.] [5] [4] [Sin].\n");
  716. printf("\n");
  717. printf("The last 6 entries of the stack are visible, and you can\n");
  718. printf("scroll to see the rest.  All operations are performed on\n");
  719. printf("the element(s) at the bottom of the stack.  The bottom\n");
  720. printf("element is called 'x' and the next element up is called 'y'.\n");
  721. printf("\n");
  722. printf("The [+/-] key changes the sign of x.  To find the cosine of\n");
  723. printf("-.22, do:\n");
  724. printf("\n");
  725. printf("[.] [2] [2] [+/-] [Cos].\n");
  726. printf("\n");
  727. printf("The [Inv] key changes the operation of some of the other keys\n");
  728. printf("so they perform the inverse operation.  It is only active for\n");
  729. printf("one keystroke.  Press [Inv] again to cancel the operation.\n");
  730. printf("\n");
  731. printf("[Sto] and [Rcl] stores and recalls a single value.\n");
  732. printf("\n");
  733. printf("[Dup2] duplicates the bottom 2 items on the stack.\n");
  734. printf("\n");
  735. printf("[Roll] rolls all the stack elements down one, and puts the\n");
  736. printf("bottom element on the top.\n");
  737. printf("\n");
  738. printf("[Exch] swaps the bottom two elements.\n");
  739. printf("\n");
  740. printf("[Int] gives the integer part.\n");
  741. printf("\n");
  742. printf("[Inv] [Frac] gives the fractional part.\n");
  743. printf("\n");
  744. printf("[Clr] clears the bottom element to zero.  Use this when you\n");
  745. printf("get some kind of error\n");
  746. printf("\n");
  747. printf("[B10] and [B16] put you in base 10 or base 16 mode.  Numbers\n");
  748. printf("with fractional parts are always displayed in base 10.  In\n");
  749. printf("base 16 mode, the keys [a] through [f] are used for numeric\n");
  750. printf("entry.  They do nothing, otherwise.\n");
  751. printf("\n");
  752. printf("[And], [Or] and [Not] are logical operations on 32 bit\n");
  753. printf("integers.  If there's a fractional part, they don't do\n");
  754. printf("anything.\n");
  755. printf("\n");
  756. printf("To remember a sequence of keystrokes, press [Prog], then the\n");
  757. printf("sequence of keystrokes, and then [Prog] again.  For example,\n");
  758. printf("if you want to calculate x^2 + y^2 repeatedly, where x and y\n");
  759. printf("are the two bottom entries of the stack, do this:\n");
  760. printf("\n");
  761. printf("[Prog] [Inv] [x^2] [Exch] [Inv] [x^2] [+] [Prog].\n");
  762. printf("\n");
  763. printf("Then, to calculate 5^2+7^2, do this:\n");
  764. printf("\n");
  765. printf("[5] [Enter] [7] [Run].\n");
  766. printf("\n");
  767. printf("The following keys from the computer keyboard are understood\n");
  768. printf("by calc:\n");
  769. printf("\n");
  770. printf("[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [.],\n");
  771. printf("[Enter], [+], [-], [*], [/], [a], [b], [c], [d], [e], [f].\n");
  772. printf("\n");
  773. printf("The [Deg]/[Rad] key shows the current angle mode.  Press\n");
  774. printf("it to get the other angle mode.\n");
  775. printf("\n------------------------------------------\n\n");
  776. }
  777.